/**
 ******************************************************************************
 * @file    Templates_LL/Src/stm32F1xx_it.c
 * @author  MCD Application Team
 * @brief   Main Interrupt Service Routines.
 *          This file provides temp1late for all exceptions handler and
 *          peripherals interrupt service routine.
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2017 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_it.h"
#include "tusb.h"
#include "icm20948.h"

/** @addtogroup STM32F1xx_LL_Examples
 * @{
 */

/** @addtogroup Templates_LL
 * @{
 */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/******************************************************************************/
/*            Cortex-M3 Processor Exceptions Handlers                         */
/******************************************************************************/

/**
 * @brief  This function handles NMI exception.
 * @param  None
 * @retval None
 */
void NMI_Handler(void)
{
}

/**
 * @brief  This function handles Hard Fault exception.
 * @param  None
 * @retval None
 */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}

/**
 * @brief  This function handles Memory Manage exception.
 * @param  None
 * @retval None
 */
void MemManage_Handler(void)
{
  /* Go to infinite loop when Memory Manage exception occurs */
  while (1)
  {
  }
}

/**
 * @brief  This function handles Bus Fault exception.
 * @param  None
 * @retval None
 */
void BusFault_Handler(void)
{
  /* Go to infinite loop when Bus Fault exception occurs */
  while (1)
  {
  }
}

/**
 * @brief  This function handles Usage Fault exception.
 * @param  None
 * @retval None
 */
void UsageFault_Handler(void)
{
  /* Go to infinite loop when Usage Fault exception occurs */
  while (1)
  {
  }
}

/**
 * @brief  This function handles SVCall exception.
 * @param  None
 * @retval None
 */
void SVC_Handler(void)
{
}

/**
 * @brief  This function handles Debug Monitor exception.
 * @param  None
 * @retval None
 */
void DebugMon_Handler(void)
{
}

/**
 * @brief  This function handles PendSVC exception.
 * @param  None
 * @retval None
 */
void PendSV_Handler(void)
{
}

/**
 * @brief  This function handles SysTick Handler.
 * @param  None
 * @retval None
 */
void SysTick_Handler(void)
{
}

/******************************************************************************/
/*                 STM32F1xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f1xx.s).                                               */
/******************************************************************************/

/**
 * @brief  USB发送中断
 * @param  None
 * @retval None
 */
void USB_HP_CAN1_TX_IRQHandler(void)
{
  tud_int_handler(0);
  tud_task();
}

/**
 * @brief  USB接收中断
 * @param  None
 * @retval None
 */
void USB_LP_CAN1_RX0_IRQHandler(void)
{
  tud_int_handler(0);
  tud_task();
}

/**
 * @brief   USART1 空闲中断
 * @param   None
 * @retval  None
 */
void USART1_IRQHandler(void)
{
  //【XXX】：空闲中断拿来干什么啊？
  if (LL_USART_IsEnabledIT_IDLE(USART1) && LL_USART_IsActiveFlag_IDLE(USART1))
  {
    /* 1. 暂时关闭 DMA 通道，进行数据转存，防止缓存过程中数据改变 */
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_5);
    /* 2. 清除中断标志位 */
    LL_USART_ClearFlag_IDLE(USART1);
    /* 3. 数据转存，这里将串口缓冲区中的数据拷贝到 sdat 结构体中 */
    suart1.rxlen = USART_BUF_LEN - LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_5); // 获取接收数据长度
    memcpy(sdat.buf, suart1.rxbuf, suart1.rxlen);                                // 拷贝数据
    sdat.len = suart1.rxlen;
    //【XXX】：这个标志位是干什么用的？
    suart1.rxflag = 1;
    /* 4. 重新启动 DMA 接受通道，绑定缓冲区，设置接受数据长度 */
    LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_5, (uint32_t)suart1.rxbuf); // 缓存地址
    LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_5, USART_BUF_LEN);             // 缓存大小
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_5);                            // 使能通道
  }
  else
  {
    // Call Error function
    NVIC_DisableIRQ(USART1_IRQn); // 关闭串口中断
  }
}

/**
 * @brief  This function handles DMA1 interrupt request.
 * @param  None
 * @retval None
 */
void DMA1_Channel4_IRQHandler(void)
{

  if (LL_DMA_IsActiveFlag_TC4(DMA1))
  {
    LL_DMA_ClearFlag_TC4(DMA1);
    //【XXX】：为什么不再 DMA 传输完成后拷贝数据？为什么要在 UART 空闲中断中拷贝数据？
  }
  else if (LL_DMA_IsActiveFlag_TE4(DMA1))
  {
    /* Disable DMA1 Tx Channel */
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_4);

    /* Disable DMA1 Rx Channel */
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_5);
  }
}

/**
 * @brief  This function handles DMA1 interrupt request.
 * @param  None
 * @retval None
 */
void DMA1_Channel5_IRQHandler(void)
{

  if (LL_DMA_IsActiveFlag_TC5(DMA1))
  {
    LL_DMA_ClearFlag_TC5(DMA1);
  }
  else if (LL_DMA_IsActiveFlag_TE5(DMA1))
  {
    /* Disable DMA1 Tx Channel */
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_4);

    /* Disable DMA1 Rx Channel */
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_5);
  }
}

/**
 * @brief  This function handles TIM2 update interrupt.
 * @param  None
 * @retval None
 */
void TIM2_IRQHandler(void)
{
  /* Check whether update interrupt is pending */
  if (LL_TIM_IsActiveFlag_UPDATE(TIM2) == 1)
  {
    /* Clear the update interrupt flag*/
    LL_TIM_ClearFlag_UPDATE(TIM2);
    //【TODO】：编写 TIM2 中断回调函数，用于定时发送数据给 vofa
  }
}

/**
 * @brief  This function handles EXTI line 15 update interrupt.
 * @param  None
 * @retval None
 */
void EXTI15_10_IRQHandler(void)
{
  /* Manage Flags */
  if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_15) != RESET)
  {
    LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_15);
    ICMIntCallback();
  }
}

/**
 * @}
 */

/**
 * @}
 */
